﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FurStudy.Core
{
    /// <summary>
    /// AsyncLocal<T>方式
    /// AsyncLocal<T>可以说是进程内共享数据的大利器，可以通过该类实现跨线程、异步控制流中共享数据
    /// </summary>
    public class AsyncLocalDemo
    {
        static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
        static ThreadLocal<string> _threadLocalString = new ThreadLocal<string>();

        static async Task AsyncMethodA()
        {
            // 使用不同的AsyncLocal值启动多个异步方法调用
            // 我们还设置ThreadLocal值，以演示这两种机制的不同之处
            _asyncLocalString.Value = "Value 1";
            _threadLocalString.Value = "Value 1";
            var t1 = AsyncMethodB("Value 1");

            _asyncLocalString.Value = "Value 2";
            _threadLocalString.Value = "Value 2";
            var t2 = AsyncMethodB("Value 2");

            // t1、t2两者都回调
            await t1;
            await t2;
        }

        static async Task AsyncMethodB(string expectedValue)
        {
            Console.WriteLine("Entering AsyncMethodB.");
            Console.WriteLine("   Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'",
                              expectedValue, _asyncLocalString.Value, _threadLocalString.Value);
            await Task.Delay(100);
            Console.WriteLine("Exiting AsyncMethodB.");
            Console.WriteLine("   Expected '{0}', got '{1}', ThreadLocal value is '{2}'",
                              expectedValue, _asyncLocalString.Value, _threadLocalString.Value);
        }

        static async Task Main(string[] args)
        {
            await AsyncMethodA();
        }

        // The example displays the following output:
        //   Entering AsyncMethodB.
        //      Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1'
        //   Entering AsyncMethodB.
        //      Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2'
        //   Exiting AsyncMethodB.
        //      Expected 'Value 2', got 'Value 2', ThreadLocal value is ''
        //   Exiting AsyncMethodB.
        //      Expected 'Value 1', got 'Value 1', ThreadLocal value is ''
    }
}
